home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / program / oxcc1434.zip / SRC / OBJ4LB.C < prev    next >
C/C++ Source or Header  |  1995-10-24  |  22KB  |  1,017 lines

  1. /* obj4lb.c    -- fiddle with symbols in an a.out or coff format file 
  2. ** Copyright (C) 1995    Norman D. Culver    All rights reserved.
  3. **
  4. ** COMPILE: (using djcc v1.12)
  5. **        gcc -O2 -o obj4lb obj4lb.c
  6. **        coff2exe -s go32.exe obj4lb
  7. */
  8.  
  9. #include <dos.h>
  10. #include <limits.h>
  11. #include <sys/types.h>
  12. #include <stdlib.h>
  13. #include <stdarg.h>
  14. #include <memory.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <binimg.h>
  18.  
  19. #define coff_sym_is_fortrancommon(p) \
  20.     ((p->e_sclass == C_EXT) && (p->e_scnum == 0) && (p->e_value != 0))
  21. #define coff_sym_is_undefined(p) \
  22.     ((p->e_scnum == 0) && (p->e_sclass == C_EXT))
  23. #define coff_sym_is_global(p) \
  24.     (p->e_sclass == C_EXT)
  25.  
  26. /* USEFUL DEFINITIONS */
  27. #ifndef __GNUC__
  28. typedef unsigned int u_int;
  29. typedef unsigned char u_char;
  30. typedef unsigned short u_short;
  31. typedef unsigned long u_long;
  32. #endif
  33. typedef union {
  34.   u_short val;
  35.   u_char b[2];
  36. } SVAL;
  37.  
  38. typedef union {
  39.   u_long a0;
  40.   void *a1;
  41.   struct {
  42.     SVAL offset;
  43.     SVAL seg_addr;
  44.   }a2;
  45. } ADDR;
  46.  
  47. typedef struct _exports {
  48.     struct _exports *fptr;
  49.     char *name;
  50.     int len;
  51. } EXPORTS;
  52.  
  53. typedef struct _renames {
  54.     struct _renames *fptr;
  55.     char *oldname;
  56.     int oldlen;
  57.     char *newname;
  58.     int newlen;
  59. } RENAMES;
  60.  
  61. typedef struct _movdat {
  62.     struct _movdat *fptr;
  63.     unsigned long offset;
  64. } MOVDAT, *PMOVDAT;
  65.  
  66. typedef struct relocation_info RELINFO;
  67.  
  68. #define round_up(size,amt) \
  69. ((size&(amt-1)) ? size+(amt-(size&(amt-1))) : size)
  70.  
  71. /* LOCAL VARIABLES */
  72. static char infile[128];
  73. static char outfile[128];
  74. static char lb4file[128];
  75. static struct exec header;
  76. static FILE *ifd, *lb4fd, *ofd;
  77. static EXPORTS exports;
  78. static RENAMES renames;
  79. static EXPORTS *lexports;
  80. static RENAMES *lrenames;
  81. static MOVDAT moves;
  82. static MOVDAT *lmoves;
  83. static int rename_diftot;
  84. static long lowoffset;
  85. static char *strtbl;
  86. static char *nstrtbl;
  87. static long strsize;
  88. static long nstrsize;
  89. static int nsyms;
  90.  
  91. /* INPUT DATA FROM THE .o FILE */
  92.  
  93. static NLIST *symtbl;
  94. static char *text;
  95. static RELINFO *text_relocs;
  96. static int n_text_relocs;
  97. static char *data;
  98. static RELINFO *data_relocs;
  99. static int n_data_relocs;
  100.  
  101. /* coff stuff */
  102. typedef struct oxhdr {
  103.     unsigned short info;
  104.     unsigned short machine;
  105.     unsigned start_addr;
  106.     unsigned text_vaddr;
  107.     unsigned text_size;
  108.     unsigned text_fileaddr;
  109.     unsigned data_vaddr;
  110.     unsigned data_size;
  111.     unsigned data_fileaddr;
  112.     unsigned bss_vaddr;
  113.     unsigned bss_size;
  114.     unsigned image_size;
  115.     unsigned text_reloc_fileaddr;
  116.     unsigned text_reloc_size;
  117.     unsigned text_reloc_cnt;
  118.     unsigned data_reloc_fileaddr;
  119.     unsigned data_reloc_size;
  120.     unsigned data_reloc_cnt;
  121.     unsigned symbols_fileaddr;
  122.     unsigned symbols_size;
  123.     unsigned symbols_cnt;
  124.     unsigned strings_fileaddr;
  125.     unsigned strings_size;
  126.     unsigned section_headers_size;
  127. } OXHDR, *POXHDR;
  128.  
  129. typedef struct {
  130.     void *addr;
  131.     long size;    
  132.     unsigned long fileptr;
  133.     long cnt;
  134. } BUFS, *PBUFS;
  135.  
  136. static OXHDR xhdr;
  137. static unsigned char scntype[128];
  138. static PSCNHDR t,d,b,q,s;
  139. static PBUFS sbf;
  140. static PBUFS rbf;
  141. static PBUFS lbf;
  142. static PCOFF_SYMBOL coff_symtbl;
  143. static short bss_section;
  144.  
  145. /* start of subroutines */
  146.  
  147. static void *
  148. xmalloc (long n)
  149. {
  150. void *p;
  151.  
  152.   p = calloc (1,(size_t)n);
  153.   if (n > 0 && p == 0)
  154.   {
  155.     puts ("obj4lb: virtual memory exhausted");
  156.     exit (1);
  157.   }
  158.   return p;
  159. }
  160. static int
  161. isglobal(char *str)
  162. {
  163. EXPORTS *l = &exports;
  164.  
  165.     while(l->fptr)
  166.     {
  167.         l = l->fptr;
  168.         if(!strcmp(str, l->name))
  169.             return 1;
  170.     }
  171.     return 0;
  172. }
  173. static RENAMES *
  174. isrenamed(char *str)
  175. {
  176. RENAMES *r = &renames;
  177.  
  178.     while(r->fptr)
  179.     {
  180.         r = r->fptr;
  181.         if(!strcmp(str, r->oldname))
  182.             return r;
  183.     }
  184.     return NULL;
  185. }
  186. static void
  187. aout_get_rid_of_fortrancommon(NLIST *sp, int symidx, int setglobal)
  188. {/* move fortrancommon symbols to the bss segment */
  189. u_long bssbase = N_BSSADDR(header);
  190. u_long bssoffset = round_up(header.a_bss, sizeof(int));
  191. u_long symbsize = sp->n_value;
  192. u_long bssaddr = bssbase + bssoffset;
  193. RELINFO *r;
  194. int i;
  195. void *ldata;
  196.  
  197.     sp->n_value = bssaddr;
  198.     if(setglobal)
  199.         sp->n_type = N_BSS|N_EXT;
  200.     else
  201.         sp->n_type = N_BSS;
  202.     header.a_bss = bssoffset + symbsize;
  203.  
  204.     /* adjust all relocs which refence this variable */
  205.     for(i = 0, r=text_relocs; i < n_text_relocs; ++i, ++r)
  206.     {
  207.         if(r->r_extern && r->r_symbolnum == symidx)
  208.         {
  209.             ldata = &text[r->r_address];
  210.             r->r_extern = 0;
  211.             r->r_symbolnum = N_BSS;
  212.             if(r->r_length == 2)
  213.                 *((long *)ldata) += bssaddr;
  214.             else
  215.             {
  216.                 puts("4lb: non 32bit reloc encountered");
  217.                 exit(1);
  218.             }
  219.         }
  220.     }
  221.     for(i = 0, r=data_relocs; i < n_data_relocs; ++i, ++r)
  222.     {
  223.         if(r->r_extern && r->r_symbolnum == symidx)
  224.         {
  225.             ldata = &data[r->r_address];
  226.             r->r_extern = 0;
  227.             r->r_symbolnum = N_BSS;
  228.             if(r->r_length == 2)
  229.                 *((long *)ldata) += bssaddr;
  230.             else
  231.             {
  232.                 puts("4lb: non 32bit reloc encountered");
  233.                 exit(1);
  234.             }
  235.         }
  236.     }
  237. }
  238. static void
  239. aout_adjust_symbol(long oldoffset, long newoffset, int setglobal)
  240. {
  241. NLIST *sp;
  242. int i;
  243.  
  244.     for(i = 0, sp = symtbl; i < nsyms; ++i, ++sp)
  245.     {
  246.         if(sp->n_un.n_strx == oldoffset)
  247.         {/* newoffset is set negative to avoid reuse */
  248.             sp->n_un.n_strx = newoffset | 0x80000000;
  249.             if(sym_is_fortrancommon(sp))
  250.                 aout_get_rid_of_fortrancommon(sp, i, setglobal);
  251.             else if(setglobal)
  252.                 sp->n_type |= N_EXT;
  253.             else if(!sym_is_undefined(sp))
  254.                 sp->n_type &= ~N_EXT;
  255.             return;
  256.         }
  257.     }
  258. }
  259. static void
  260. coff_get_rid_of_fortrancommon(COFF_SYMBOL *sp, int symidx, int setglobal)
  261. {/* move fortrancommon symbols to the bss segment */
  262. PCOFF_HDR p = (PCOFF_HDR)&header;
  263. u_long bssbase = b->s_vaddr;
  264. u_long bssoffset = round_up(b->s_size, sizeof(int));
  265. u_long symbsize = sp->e_value;
  266. u_long bssaddr = bssbase + bssoffset;
  267. int i, j;
  268.  
  269.     sp->e_value = bssaddr;
  270.     sp->e_scnum = bss_section;
  271.     if(setglobal)
  272.         sp->e_sclass = C_EXT;
  273.     else
  274.         sp->e_sclass = C_STAT;
  275.     b->s_size = round_up(bssoffset + symbsize, sizeof(int));
  276.  
  277.     /* adjust all relocs which reference this variable */
  278.     for(i = 0; i < p->f_nscns; ++i)
  279.     {
  280.     COFF_RELOC *r;
  281.  
  282.         if((r = rbf[i].addr))
  283.         {
  284.         int cnt = rbf[i].cnt;
  285.         char *scndata = sbf[i].addr;
  286.         unsigned long s_vaddr = s[i].s_vaddr;
  287.  
  288.             for(j = 0; j < cnt; ++j, ++r)
  289.             {
  290.                 if(r->r_symndx == symidx)
  291.                 {
  292.                 void *ldata = &scndata[r->u.r_vaddr - s_vaddr];
  293.                     if(r->r_type == 0x0006)
  294.                     {
  295.                         *((long *)ldata) += bssaddr - symbsize;
  296.                     }
  297.                     else if(r->r_type == 0x0007)
  298.                     {
  299.                         puts("4lb: type 7 reloc encountered");
  300.                         exit(1);
  301.                     }
  302.                     else if(r->r_type == 0x0014)
  303.                     {
  304.                         puts("4lb: pcrel comdef encountered");
  305.                         exit(1);
  306.                     }
  307.                     else
  308.                     {
  309.                         puts("4lb: non 32bit reloc encountered");
  310.                         exit(1);
  311.                     }
  312.                 }
  313.             }
  314.         }
  315.     }
  316. }
  317. static void
  318. coff_adjust_symbol(long oldoffset, long newoffset, int setglobal)
  319. {
  320. COFF_SYMBOL *sp;
  321. int i;
  322.  
  323.     for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
  324.     {
  325.         if(sp->e.e.e_offset == oldoffset)
  326.         {/* newoffset is set negative to avoid reuse */
  327.             sp->e.e.e_offset = newoffset | 0x80000000;
  328.             if(coff_sym_is_fortrancommon(sp))
  329.                 coff_get_rid_of_fortrancommon(sp, i, setglobal);
  330.             else if(setglobal)
  331.                 sp->e_sclass = C_EXT;
  332.             else if(!coff_sym_is_undefined(sp))
  333.             {
  334.                 if(coff_sym_is_global(sp))
  335.                     sp->e_sclass = C_STAT;
  336.             }
  337.         }
  338.         if(sp->e_numaux)
  339.         {/* ignore aux records */
  340.             i += sp->e_numaux;
  341.             sp += sp->e_numaux;
  342.         }
  343.     }
  344. }
  345. static void
  346. adjust_strings(int format_fudge)
  347. {/* HERE'S THE BEEF -- WRITE A NEW STRING TABLE AND ADJUST SYMTAB */
  348. long istroff = lowoffset;
  349. long ostroff = lowoffset;
  350. char *ip, *ep, *op;
  351. int i;
  352.  
  353.     nstrsize = strsize + rename_diftot;
  354.     nstrtbl = xmalloc(nstrsize+12);
  355.     ip = strtbl+lowoffset;
  356.     op = nstrtbl+lowoffset;
  357.     ep = ip + strsize;
  358.  
  359.     while(ip < ep)
  360.     {/* scan over each of the strings in the old string table */
  361.     int global;
  362.     int    istrlen = strlen(ip);
  363.     int olen;
  364.     RENAMES *r;
  365.         if(istrlen > 0)
  366.         {
  367.             if((r = isrenamed(ip)))
  368.             {/* change the string on output */
  369.                 strcpy(op, r->newname);
  370.                 op += r->newlen+1;
  371.                 olen = r->newlen+1;
  372.                 global = isglobal(r->newname);
  373.             }
  374.             else
  375.             {/* use the